package com.meilai.project.service.business.media.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilai.project.controller.mini.dto.MiniSourceMTDTO;
import com.meilai.project.dto.business.media.MediaTypeDTO;
import com.meilai.project.entity.media.MediaType;
import com.meilai.project.mapper.business.media.MediaTypeMapper;
import com.meilai.project.service.business.media.MediaTypeService;
import com.meilai.project.vo.business.media.MediaTypeTreeVO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author 张驰
 * @date 2022/1/9 23:02
 */
@Service
public class MediaTypeServiceImpl extends ServiceImpl<MediaTypeMapper, MediaType> implements MediaTypeService {
    @Override
    public List<MediaTypeTreeVO> list(String name) {
        List<MediaTypeTreeVO> list = baseMapper.page(name);
        List<MediaTypeTreeVO> resultList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list)) {
            Map<Long, List<MediaTypeTreeVO>> map = list.stream().map(item -> {
                MediaTypeTreeVO vo = new MediaTypeTreeVO();
                BeanUtils.copyProperties(item, vo);
                vo.setChildren(new ArrayList<>());
                return vo;
            }).collect(Collectors.groupingBy(MediaTypeTreeVO::getPid));
            resultList.addAll(map.get(0L));
            resultList.forEach(item -> {
                treeForEach(map, item);
            });
        }
        return resultList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean edit(MediaType mediaType) {
        MediaType oldData = this.getById(mediaType.getId());
        if (!oldData.getPid().equals(mediaType.getPid())) {
            // step1 检查老数据指向的pid数据是否还有子节点
            if (!oldData.getPid().equals(0L)) {
                int count = this.count(Wrappers.<MediaType>lambdaQuery().eq(MediaType::getPid, oldData.getPid()).ne(MediaType::getId, mediaType.getId()));
                this.update(Wrappers.<MediaType>lambdaUpdate().set(MediaType::getIs_leaf, !(count > 0)).eq(MediaType::getId, oldData.getPid()));
            }
            // step2 修改新数据的is_leaf
            this.update(Wrappers.<MediaType>lambdaUpdate().set(MediaType::getIs_leaf, false).eq(MediaType::getId, mediaType.getPid()));
            // step3 修改数据的rid指向的新数据的rid
            MediaType newParentData = this.getById(mediaType.getPid());
            if (mediaType.getPid().equals(0L)) {
                mediaType.setRid(mediaType.getId());
            } else {
                mediaType.setRid(newParentData.getRid());
            }
        }
        return this.update(Wrappers.<MediaType>lambdaUpdate()
                .set(MediaType::getName, mediaType.getName())
                .set(MediaType::getPid, mediaType.getPid())
                .set(MediaType::getRid, mediaType.getRid())
                .set(MediaType::getClassification_id, mediaType.getClassification_id())
                .set(MediaType::getHas_duration_and_times, mediaType.getHas_duration_and_times())
                .set(MediaType::getHas_multiple_spec, mediaType.getHas_multiple_spec())
                .set(MediaType::getHas_price_day, mediaType.getHas_price_day())
                .set(MediaType::getHas_price_week, mediaType.getHas_price_week())
                .set(MediaType::getHas_price_month, mediaType.getHas_price_month())
                .set(MediaType::getProject_sort_id, mediaType.getProject_sort_id())
                .eq(MediaType::getId, mediaType.getId()));
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean save(MediaTypeDTO mediaTypeDTO) {
        MediaType mediaType = new MediaType();
        BeanUtils.copyProperties(mediaTypeDTO, mediaType);
        mediaType.setIs_leaf(true);
        // flag为true pid不是0 需要找到rid
        boolean flag = mediaType.getPid() != null && mediaType.getPid() != 0;
        if (mediaType.getPid() == null) {
            mediaType.setPid(0L);
        }
        MediaType one = this.getById(mediaType.getPid());
        if (one != null && one.getIs_leaf()) {
            one.setIs_leaf(false);
            this.updateById(one);
        }
        return this.save(mediaType) && this.update(Wrappers.<MediaType>lambdaUpdate().set(MediaType::getRid, flag ? one.getRid() : mediaType.getId()).eq(MediaType::getId, mediaType.getId()));
    }

    @Override
    public List<MediaType> getTypeList(Long media_type_id) {
        return baseMapper.getTypeList(media_type_id);
    }

    /**
     * 组装树形结构
     *
     * @param collect
     * @param treeMenuNode
     */
    private static void treeForEach(Map<Long, List<MediaTypeTreeVO>> collect, MediaTypeTreeVO treeMenuNode) {
        List<MediaTypeTreeVO> treeMenuNodes = collect.get(treeMenuNode.getId());
        if (collect.get(treeMenuNode.getId()) != null) {
            treeMenuNode.setChildren(treeMenuNodes);
            treeMenuNode.getChildren().forEach(t -> {
                treeForEach(collect, t);
            });
        }
    }

    @Override
    public List<MiniSourceMTDTO> getAllTypeForMini() {
        return baseMapper.getAllTypeForMini();
    }
}
